<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>Incident Command Board 演示</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css">
  <style>
    body {
      background: #101a2b;
      margin: 0;
      padding: 0;
      font-family: 'Microsoft YaHei', Arial, sans-serif;
      color: #e4f1fe;
      min-height: 100vh;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: flex-start;
    }
    .screen-header {
      width: 100vw;
      max-width: 100vw;
      height: 90px;
      background: linear-gradient(90deg, rgba(64,158,255,0.18) 0%, rgba(56,189,248,0.12) 100%);
      box-shadow: 0 4px 32px 0 rgba(64,158,255,0.08);
      display: flex;
      align-items: center;
      justify-content: center;
      position: relative;
      z-index: 10;
      margin-bottom: 2vh;
    }
    .screen-header-title {
      font-size: 2.8vw;
      color: #38bdf8;
      font-weight: 700;
      letter-spacing: 0.2em;
      text-shadow: 0 0 24px #38bdf8cc, 0 2px 0 #0f1a40;
      display: flex;
      align-items: center;
      justify-content: center;
      padding: 0 2vw;
      user-select: none;
    }
    .screen-header-title .fa {
      font-size: 2.2vw;
      margin-right: 1vw;
      color: #FFD700;
      filter: drop-shadow(0 0 8px #FFD70088);
    }
    .incident-board-container {
      width: 1200px;
      max-width: 98vw;
      height: 80vh;
      min-height: 480px;
      background: rgba(20, 30, 60, 0.92);
      border-radius: 18px;
      box-shadow: 0 0 32px 0 rgba(0,191,255,0.10), 0 0 0 2px rgba(64,158,255,0.12) inset;
      border: 1.5px solid rgba(64,158,255,0.18);
      position: relative;
      overflow: hidden;
      display: flex;
      flex-direction: column;
      padding: 0 0 0 0;
      backdrop-filter: blur(6px);
    }
    .incident-board-title {
      font-size: 22px;
      font-weight: 600;
      color: #38bdf8;
      letter-spacing: 2px;
      text-align: left;
      margin: 22px 0 10px 32px;
      text-shadow: 0 0 10px #38bdf844;
      user-select: none;
      display: flex;
      align-items: center;
      justify-content: flex-start;
    }
    .incident-board-actions {
      display: flex;
      align-items: center;
      gap: 18px;
      margin-left: auto;
      margin-right: 32px;
    }
    .incident-filter-btn, .incident-resume-btn {
      background: linear-gradient(90deg, #38bdf8 0%, #409EFF 100%);
      color: #fff;
      border: none;
      border-radius: 20px;
      font-size: 16px;
      font-weight: 500;
      padding: 8px 24px;
      margin-left: 10px;
      cursor: pointer;
      box-shadow: 0 2px 8px 0 rgba(56,189,248,0.08);
      transition: background 0.2s, box-shadow 0.2s;
      outline: none;
      display: flex;
      align-items: center;
      gap: 8px;
    }
    .incident-filter-btn:hover, .incident-resume-btn:hover {
      background: linear-gradient(90deg, #409EFF 0%, #38bdf8 100%);
      box-shadow: 0 0 16px 2px #38bdf8cc;
    }
    .incident-list {
      flex: 1;
      overflow-y: auto;
      padding: 0 0 18px 0;
      margin: 0;
      position: relative;
    }
    /* 定制滚动条 */
    .incident-list::-webkit-scrollbar {
      width: 7px;
      background: transparent;
    }
    .incident-list::-webkit-scrollbar-thumb {
      background: linear-gradient(180deg, #38bdf8 0%, #409EFF 100%);
      border-radius: 6px;
      box-shadow: 0 0 8px #38bdf8cc;
    }
    .incident-list::-webkit-scrollbar-track {
      background: transparent;
    }
    /* 卡片成长条样式 */
    .incident-card {
      display: flex;
      flex-direction: row;
      background: rgba(255,255,255,0.04);
      border-radius: 12px;
      margin: 18px 32px 0 32px;
      box-shadow: 0 2px 16px 0 rgba(64,158,255,0.08);
      position: relative;
      min-height: 120px;
      min-width: 0;
      overflow: hidden;
      border: 1.5px solid rgba(64,158,255,0.10);
      transition: box-shadow 0.3s, background 0.3s, border 0.3s, filter 0.3s;
      animation: card-unfold 0.7s cubic-bezier(.4,1.6,.4,1);
      width: calc(100% - 64px);
      max-width: 100%;
    }
    @keyframes card-unfold {
      0% {
        opacity: 0;
        transform: scaleY(0.2) scaleX(0.95);
        filter: blur(8px);
      }
      40% {
        opacity: 1;
        filter: blur(2px);
        box-shadow: 0 0 32px 0 #38bdf8cc;
      }
      100% {
        opacity: 1;
        transform: scaleY(1) scaleX(1);
        filter: blur(0);
      }
    }
    .incident-card.archiving {
      animation: card-archive 1.2s forwards;
    }
    @keyframes card-archive {
      0% { filter: none; opacity: 1; }
      60% { filter: grayscale(0.7) blur(1px); opacity: 0.5; }
      100% { filter: grayscale(1) blur(4px); opacity: 0; height: 0; margin: 0 32px; padding: 0; }
    }
    .incident-card.flash {
      animation: card-flash 0.4s;
    }
    @keyframes card-flash {
      0% { box-shadow: 0 0 32px 0 #FFD700cc; }
      100% { box-shadow: 0 2px 16px 0 rgba(64,158,255,0.08); }
    }
    .incident-status-zone {
      width: 38px;
      min-width: 38px;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      position: relative;
      background: transparent;
    }
    .incident-status-bar {
      width: 12px;
      height: 90px;
      border-radius: 8px;
      margin: 0 auto 0 auto;
      display: flex;
      align-items: center;
      justify-content: center;
      position: relative;
      box-shadow: 0 0 16px 2px rgba(64,158,255,0.10);
      transition: background 0.4s, box-shadow 0.4s;
    }
    .incident-status-bar.pending {
      background: linear-gradient(180deg, #FFA500 60%, #fffbe6 100%);
      box-shadow: 0 0 18px 4px #FFA50099, 0 0 8px 2px #fffbe6cc;
      animation: status-pulse 2s infinite;
    }
    .incident-status-bar.processing {
      background: linear-gradient(180deg, #00BFFF 60%, #e0f7ff 100%);
      box-shadow: 0 0 14px 2px #00BFFF99;
    }
    .incident-status-bar.completed {
      background: linear-gradient(180deg, #28A745 60%, #e0ffe6 100%);
      box-shadow: 0 0 14px 2px #28A74599;
    }
    @keyframes status-pulse {
      0% { box-shadow: 0 0 8px 2px #FFA50099; }
      50% { box-shadow: 0 0 24px 8px #FFA500cc; }
      100% { box-shadow: 0 0 8px 2px #FFA50099; }
    }
    .incident-status-icon {
      position: absolute;
      left: 50%;
      top: 50%;
      transform: translate(-50%, -50%);
      font-size: 22px;
      color: #fff;
      z-index: 2;
      transition: color 0.4s;
    }
    .incident-status-bar.processing .incident-status-icon {
      animation: spin 1.2s linear infinite;
      color: #fff;
    }
    @keyframes spin {
      0% { transform: translate(-50%, -50%) rotate(0deg); }
      100% { transform: translate(-50%, -50%) rotate(360deg); }
    }
    .incident-info-zone {
      flex: 1;
      display: flex;
      flex-direction: row;
      min-width: 0;
      padding: 18px 18px 12px 18px;
      align-items: center;
      justify-content: space-between;
      gap: 18px;
    }
    .incident-meta-header {
      display: flex;
      flex-direction: column;
      align-items: flex-start;
      margin-bottom: 0;
      min-width: 180px;
      max-width: 220px;
      flex-shrink: 0;
      gap: 8px;
    }
    .incident-id {
      font-family: 'Consolas', 'monospace';
      font-size: 17px;
      color: #b6c7e3;
      letter-spacing: 1px;
      background: rgba(64,158,255,0.08);
      border-radius: 4px;
      padding: 2px 10px;
      margin-right: 0;
      margin-bottom: 2px;
    }
    .incident-timestamp {
      font-size: 14px;
      color: #94a3b8;
      font-weight: 400;
      letter-spacing: 1px;
    }
    .incident-content {
      color: #e4f1fe;
      font-size: 19px;
      font-weight: 500;
      margin-bottom: 0;
      word-break: break-all;
      line-height: 1.7;
      text-shadow: 0 0 8px #38bdf822;
      min-height: 28px;
      opacity: 0;
      animation: content-fadein 0.7s 0.2s forwards;
      flex: 1;
      margin: 0 18px;
      max-width: 480px;
      min-width: 180px;
      display: flex;
      align-items: center;
    }
    @keyframes content-fadein {
      0% { opacity: 0; transform: translateY(-10px); }
      100% { opacity: 1; transform: translateY(0); }
    }
    .incident-attr-footer {
      display: flex;
      flex-direction: column;
      align-items: flex-end;
      justify-content: flex-end;
      min-width: 180px;
      max-width: 220px;
      gap: 10px;
    }
    .incident-attrs {
      display: flex;
      align-items: center;
      gap: 18px;
      font-size: 14px;
      color: #94a3b8;
      flex-wrap: wrap;
      justify-content: flex-end;
    }
    .incident-attrs span {
      display: flex;
      align-items: center;
      gap: 4px;
      margin-right: 8px;
    }
    .incident-attrs .fa {
      font-size: 15px;
      opacity: 0.7;
    }
    .incident-actions {
      display: flex;
      align-items: center;
      gap: 12px;
      justify-content: flex-end;
    }
    .incident-action-btn {
      display: flex;
      align-items: center;
      justify-content: center;
      font-size: 15px;
      font-weight: 500;
      border: none;
      outline: none;
      border-radius: 50px;
      padding: 7px 18px 7px 14px;
      cursor: pointer;
      opacity: 0.95;
      transition: background 0.2s, box-shadow 0.2s, transform 0.1s;
      box-shadow: 0 2px 8px 0 rgba(0,0,0,0.08);
      color: #fff;
      background: #222b3a88;
      position: relative;
      overflow: hidden;
    }
    .incident-action-btn.urge {
      background: #FFA50044;
    }
    .incident-action-btn.urge:hover, .incident-action-btn.urge:active {
      background: #FFA500;
      box-shadow: 0 0 16px 2px #FFA500cc;
      transform: scale(0.96);
    }
    .incident-action-btn.assign {
      background: #00BFFF44;
    }
    .incident-action-btn.assign:hover, .incident-action-btn.assign:active {
      background: #00BFFF;
      box-shadow: 0 0 16px 2px #00BFFFcc;
      transform: scale(0.96);
    }
    .incident-action-btn .fa {
      margin-right: 7px;
      font-size: 16px;
    }
    /* 筛选弹窗 */
    .incident-filter-modal {
      position: fixed;
      left: 0; top: 0; right: 0; bottom: 0;
      background: rgba(15,26,64,0.45);
      z-index: 9999;
      display: flex;
      align-items: center;
      justify-content: center;
      animation: modal-fadein 0.3s;
    }
    @keyframes modal-fadein {
      0% { opacity: 0; }
      100% { opacity: 1; }
    }
    .incident-filter-modal-content {
      background: rgba(20,30,60,0.98);
      border-radius: 16px;
      box-shadow: 0 0 32px 0 #38bdf8cc;
      padding: 36px 48px 32px 48px;
      min-width: 320px;
      min-height: 180px;
      display: flex;
      flex-direction: column;
      align-items: flex-start;
      gap: 22px;
      position: relative;
    }
    .incident-filter-modal-content label {
      font-size: 16px;
      color: #38bdf8;
      margin-bottom: 8px;
      font-weight: 500;
    }
    .incident-filter-modal-content select, .incident-filter-modal-content input {
      font-size: 15px;
      padding: 6px 12px;
      border-radius: 6px;
      border: 1px solid #38bdf8;
      background: #101a2b;
      color: #e4f1fe;
      margin-bottom: 12px;
      outline: none;
    }
    .incident-filter-modal-content .modal-actions {
      display: flex;
      gap: 18px;
      margin-top: 12px;
      width: 100%;
      justify-content: flex-end;
    }
    .incident-filter-modal-content button {
      background: linear-gradient(90deg, #38bdf8 0%, #409EFF 100%);
      color: #fff;
      border: none;
      border-radius: 20px;
      font-size: 15px;
      font-weight: 500;
      padding: 7px 24px;
      cursor: pointer;
      box-shadow: 0 2px 8px 0 rgba(56,189,248,0.08);
      transition: background 0.2s, box-shadow 0.2s;
      outline: none;
    }
    .incident-filter-modal-content button:hover {
      background: linear-gradient(90deg, #409EFF 0%, #38bdf8 100%);
      box-shadow: 0 0 16px 2px #38bdf8cc;
    }
    @media (max-width: 900px) {
      .incident-board-container { width: 98vw; min-width: 0; }
      .incident-card { margin: 18px 2vw 0 2vw; width: 96vw; }
      .incident-info-zone { padding: 12px 6px 8px 10px; }
      .incident-content { font-size: 15px; }
      .incident-attrs { font-size: 12px; gap: 8px; }
    }
    @media (max-width: 600px) {
      .screen-header { height: 60px; }
      .screen-header-title { font-size: 18px; padding: 0 8px; }
      .incident-board-title { font-size: 16px; }
      .incident-board-container { height: 98vh; min-height: 0; width: 99vw; }
      .incident-card { margin: 12px 1vw 0 1vw; width: 97vw; }
      .incident-info-zone { padding: 8px 2px 6px 6px; }
      .incident-content { font-size: 13px; }
      .incident-attrs { font-size: 10px; gap: 4px; }
    }
    .incident-status-bar.incident-bar-facility {
      background: linear-gradient(180deg, #38bdf8 60%, #e0f7ff 100%);
      box-shadow: 0 0 18px 4px #38bdf899, 0 0 8px 2px #e0f7ffcc;
    }
    .incident-status-bar.incident-bar-fire {
      background: linear-gradient(180deg, #ff4d4f 60%, #fff0f0 100%);
      box-shadow: 0 0 18px 4px #ff4d4f99, 0 0 8px 2px #fff0f0cc;
    }
    .incident-status-bar.incident-bar-device {
      background: linear-gradient(180deg, #f59e42 60%, #fffbe6 100%);
      box-shadow: 0 0 18px 4px #f59e4299, 0 0 8px 2px #fffbe6cc;
    }
    .incident-status-bar.incident-bar-energy {
      background: linear-gradient(180deg, #a855f7 60%, #ede9fe 100%);
      box-shadow: 0 0 18px 4px #a855f799, 0 0 8px 2px #ede9fecc;
    }
    .incident-status-bar.incident-bar-security {
      background: linear-gradient(180deg, #00BFFF 60%, #e0f7ff 100%);
      box-shadow: 0 0 18px 4px #00BFFF99, 0 0 8px 2px #e0f7ffcc;
    }
    .incident-status-bar.incident-bar-default {
      background: linear-gradient(180deg, #94a3b8 60%, #e0e7ef 100%);
      box-shadow: 0 0 18px 4px #94a3b899, 0 0 8px 2px #e0e7efcc;
    }
  </style>
</head>
<body>
  <div class="screen-header">
    <div class="screen-header-title">
      <i class="fa-solid fa-satellite-dish"></i>
      智能园区大屏 - Incident Command Board
    </div>
  </div>
  <div class="incident-board-container">
    <div style="display:flex;align-items:center;justify-content:space-between;">
      <div class="incident-board-title">
        <i class="fa-solid fa-table-list" style="margin-right:8px;"></i>告警指挥中心
      </div>
      <div class="incident-board-actions">
        <button class="incident-filter-btn" id="openFilterBtn"><i class="fa-solid fa-filter"></i>筛选</button>
        <button class="incident-resume-btn" id="resumeRealtimeBtn" style="display:none;"><i class="fa-solid fa-play"></i>恢复实时</button>
      </div>
    </div>
    <div class="incident-list" id="incidentList">
      <!-- 动态渲染 -->
    </div>
  </div>
  <div id="incidentFilterModal" class="incident-filter-modal" style="display:none;">
    <div class="incident-filter-modal-content">
      <label for="filterStatus">处理状态：</label>
      <select id="filterStatus">
        <option value="">全部</option>
        <option value="undispatched">未分派</option>
        <option value="unaccepted">未接单</option>
      </select>
      <label for="filterKeyword">关键词：</label>
      <input id="filterKeyword" type="text" placeholder="报事编号/内容/报事人..." />
      <div class="modal-actions">
        <button id="applyFilterBtn">应用筛选</button>
        <button id="closeFilterBtn">取消</button>
      </div>
    </div>
  </div>
  <script>
    // 模拟数据
    let incidentData = [
      {
        id: "evt-001",
        incidentId: "ALM20231027001",
        reporter: "王先生",
        status: "undispatched",
        content: "A栋大堂天花板漏水，情况紧急，需要立即处理！",
        location: "A栋-1F-大堂",
        timestamp: "2023-10-27 14:30:15",
        category: "设施报修",
        channel: "App上报",
        source: "业主App"
      },
      {
        id: "evt-002",
        incidentId: "ALM20231027002",
        reporter: "安保部",
        status: "unaccepted",
        content: "地下车库B2区烟雾传感器触发，已派人前往核实。",
        location: "B2-Parking-Zone-C",
        timestamp: "2023-10-27 14:28:00",
        category: "消防告警",
        channel: "系统监测",
        source: "IoT平台"
      },
      {
        id: "evt-003",
        incidentId: "ALM20231027003",
        reporter: "李女士",
        status: "undispatched",
        content: "C栋电梯内有异响，已处理完毕。",
        location: "C栋-Elevator-02",
        timestamp: "2023-10-27 14:25:10",
        category: "设备故障",
        channel: "电话",
        source: "客服中心"
      }
    ];
    let autoInject = true;
    let injectTimer = null;
    let filterActive = false;
    let filterStatus = '';
    let filterKeyword = '';
    let filteredData = [];
    let scrollTimer = null;
    let scrollPaused = false;
    let scrollIndex = 0;

    // 状态映射
    function getStatusIcon(status) {
      if (status === 'undispatched') return '<i class="fa-solid fa-triangle-exclamation"></i>';
      if (status === 'unaccepted') return '<i class="fa-solid fa-gear"></i>';
      return '';
    }
    function getStatusBarClass(status, category) {
      // category色彩映射
      let catColor = '';
      switch(category) {
        case '设施报修': catColor = 'incident-bar-facility'; break;
        case '消防告警': catColor = 'incident-bar-fire'; break;
        case '设备故障': catColor = 'incident-bar-device'; break;
        case '能耗异常': catColor = 'incident-bar-energy'; break;
        case '安防告警': catColor = 'incident-bar-security'; break;
        default: catColor = 'incident-bar-default'; break;
      }
      return 'incident-status-bar ' + status + ' ' + catColor;
    }
    function getStatusText(status) {
      if (status === 'undispatched') return '未分派';
      if (status === 'unaccepted') return '未接单';
      return '';
    }

    // 渲染
    function renderIncidentList() {
      const list = document.getElementById('incidentList');
      list.innerHTML = '';
      let data = filterActive ? filteredData : incidentData;
      data.forEach((event, idx) => {
        const card = document.createElement('div');
        card.className = 'incident-card' + (event.archiving ? ' archiving' : '');
        card.setAttribute('data-id', event.id);
        // 状态区
        const statusZone = document.createElement('div');
        statusZone.className = 'incident-status-zone';
        const statusBar = document.createElement('div');
        statusBar.className = getStatusBarClass(event.status, event.category);
        statusBar.innerHTML = `<span class="incident-status-icon">${getStatusIcon(event.status)}</span>`;
        statusZone.appendChild(statusBar);
        card.appendChild(statusZone);
        // 信息区
        const infoZone = document.createElement('div');
        infoZone.className = 'incident-info-zone';
        // meta header
        const metaHeader = document.createElement('div');
        metaHeader.className = 'incident-meta-header';
        const incidentId = document.createElement('span');
        incidentId.className = 'incident-id';
        incidentId.textContent = event.incidentId;
        metaHeader.appendChild(incidentId);
        const timestamp = document.createElement('span');
        timestamp.className = 'incident-timestamp';
        timestamp.textContent = event.timestamp;
        metaHeader.appendChild(timestamp);
        infoZone.appendChild(metaHeader);
        // content
        const content = document.createElement('div');
        content.className = 'incident-content';
        content.textContent = event.content;
        infoZone.appendChild(content);
        // footer
        const footer = document.createElement('div');
        footer.className = 'incident-attr-footer';
        // 属性组
        const attrs = document.createElement('div');
        attrs.className = 'incident-attrs';
        attrs.innerHTML =
          `<span><i class='fa-solid fa-location-dot'></i> ${event.location}</span>` +
          `<span><i class='fa-solid fa-user'></i> ${event.reporter}</span>` +
          `<span><i class='fa-solid fa-screwdriver-wrench'></i> ${event.category}</span>`;
        footer.appendChild(attrs);
        // 操作按钮组
        const actions = document.createElement('div');
        actions.className = 'incident-actions';
        // 催办
        const urgeBtn = document.createElement('button');
        urgeBtn.className = 'incident-action-btn urge';
        urgeBtn.innerHTML = '<i class="fa-solid fa-bolt"></i>催办';
        urgeBtn.onclick = e => {
          e.stopPropagation();
          urgeBtn.classList.add('flash');
          card.classList.add('flash');
          setTimeout(() => {
            urgeBtn.classList.remove('flash');
            card.classList.remove('flash');
          }, 400);
          console.log('催办', event.incidentId);
        };
        actions.appendChild(urgeBtn);
        // 分派
        const assignBtn = document.createElement('button');
        assignBtn.className = 'incident-action-btn assign';
        assignBtn.innerHTML = '<i class="fa-solid fa-user-plus"></i>分派';
        assignBtn.onclick = e => {
          e.stopPropagation();
          assignBtn.classList.add('flash');
          card.classList.add('flash');
          setTimeout(() => {
            assignBtn.classList.remove('flash');
            card.classList.remove('flash');
          }, 400);
          // 状态变更演示
          if (event.status === 'undispatched') {
            event.status = 'unaccepted';
            renderIncidentList();
          }
          console.log('分派', event.incidentId);
        };
        actions.appendChild(assignBtn);
        footer.appendChild(actions);
        infoZone.appendChild(footer);
        card.appendChild(infoZone);
        // 鼠标悬浮高亮与滚动暂停
        card.addEventListener('mouseenter', () => {
          scrollPaused = true;
          card.style.boxShadow = '0 0 32px 0 #FFD700cc, 0 2px 16px 0 rgba(64,158,255,0.08)';
        });
        card.addEventListener('mouseleave', () => {
          scrollPaused = false;
          card.style.boxShadow = '';
        });
        // 双击弹窗详细信息
        card.ondblclick = function(e) {
          showDetailDialog(event);
        };
        list.appendChild(card);
      });
    }

    // 筛选弹窗逻辑
    const openFilterBtn = document.getElementById('openFilterBtn');
    const filterModal = document.getElementById('incidentFilterModal');
    const closeFilterBtn = document.getElementById('closeFilterBtn');
    const applyFilterBtn = document.getElementById('applyFilterBtn');
    const filterStatusSel = document.getElementById('filterStatus');
    const filterKeywordInput = document.getElementById('filterKeyword');
    const resumeRealtimeBtn = document.getElementById('resumeRealtimeBtn');

    // 只保留全部、未分派、未接单
    filterStatusSel.innerHTML = '<option value="">全部</option><option value="undispatched">未分派</option><option value="unaccepted">未接单</option>';

    openFilterBtn.onclick = function() {
      filterModal.style.display = 'flex';
      filterStatusSel.value = filterStatus;
      filterKeywordInput.value = filterKeyword;
    };
    closeFilterBtn.onclick = function() {
      filterModal.style.display = 'none';
    };
    applyFilterBtn.onclick = function() {
      filterStatus = filterStatusSel.value;
      filterKeyword = filterKeywordInput.value.trim();
      filterActive = true;
      autoInject = false;
      if (injectTimer) clearInterval(injectTimer);
      resumeRealtimeBtn.style.display = '';
      filterModal.style.display = 'none';
      filteredData = incidentData.filter(ev => {
        let match = true;
        if (filterStatus && ev.status !== filterStatus) match = false;
        if (filterKeyword) {
          const kw = filterKeyword.toLowerCase();
          if (!(ev.incidentId.toLowerCase().includes(kw) || ev.content.toLowerCase().includes(kw) || ev.reporter.toLowerCase().includes(kw))) match = false;
        }
        return match;
      });
      renderIncidentList();
    };
    resumeRealtimeBtn.onclick = function() {
      filterActive = false;
      autoInject = true;
      resumeRealtimeBtn.style.display = 'none';
      renderIncidentList();
      simulateNewIncident();
    };

    // 自动向下滚动
    function startScroll() {
      const list = document.getElementById('incidentList');
      if (scrollTimer) clearInterval(scrollTimer);
      scrollTimer = setInterval(() => {
        if (scrollPaused) return;
        list.scrollTop += 1;
        // 到底部后回到顶部
        if (list.scrollTop + list.clientHeight >= list.scrollHeight - 2) {
          list.scrollTop = 0;
        }
      }, 40);
    }

    // 详细信息弹窗
    function showDetailDialog(event) {
      let dlg = document.getElementById('incidentDetailDialog');
      if (!dlg) {
        dlg = document.createElement('div');
        dlg.id = 'incidentDetailDialog';
        dlg.style.position = 'fixed';
        dlg.style.left = '0';
        dlg.style.top = '0';
        dlg.style.right = '0';
        dlg.style.bottom = '0';
        dlg.style.background = 'rgba(15,26,64,0.45)';
        dlg.style.zIndex = '99999';
        dlg.style.display = 'flex';
        dlg.style.alignItems = 'center';
        dlg.style.justifyContent = 'center';
        dlg.innerHTML = '';
        document.body.appendChild(dlg);
      }
      dlg.innerHTML = `<div style="background:rgba(20,30,60,0.98);border-radius:16px;box-shadow:0 0 32px 0 #38bdf8cc;padding:36px 48px 32px 48px;min-width:320px;min-height:180px;max-width:90vw;max-height:90vh;overflow:auto;position:relative;">
        <div style='font-size:20px;color:#38bdf8;font-weight:600;margin-bottom:18px;'>告警详细信息</div>
        <div style='margin-bottom:10px;'><b>报事编号：</b>${event.incidentId}</div>
        <div style='margin-bottom:10px;'><b>报事时间：</b>${event.timestamp}</div>
        <div style='margin-bottom:10px;'><b>处理状态：</b>${getStatusText(event.status)}</div>
        <div style='margin-bottom:10px;'><b>报事内容：</b>${event.content}</div>
        <div style='margin-bottom:10px;'><b>报事人：</b>${event.reporter}</div>
        <div style='margin-bottom:10px;'><b>房号：</b>${event.location}</div>
        <div style='margin-bottom:10px;'><b>报事类别：</b>${event.category}</div>
        <div style='margin-bottom:10px;'><b>报事方式：</b>${event.channel}</div>
        <div style='margin-bottom:10px;'><b>报事来源：</b>${event.source}</div>
        <button id='closeDetailDialogBtn' style='margin-top:18px;background:linear-gradient(90deg,#38bdf8 0%,#409EFF 100%);color:#fff;border:none;border-radius:20px;font-size:15px;font-weight:500;padding:7px 24px;cursor:pointer;box-shadow:0 2px 8px 0 rgba(56,189,248,0.08);transition:background 0.2s,box-shadow 0.2s;outline:none;'>关闭</button>
      </div>`;
      dlg.style.display = 'flex';
      document.getElementById('closeDetailDialogBtn').onclick = function() {
        dlg.style.display = 'none';
      };
    }

    // 模拟新告警注入
    function simulateNewIncident() {
      if (!autoInject) return;
      if (injectTimer) clearInterval(injectTimer);
      injectTimer = setInterval(() => {
        if (!autoInject) return;
        const now = new Date();
        const id = 'evt-' + Math.floor(Math.random()*10000);
        const incidentId = 'ALM' + now.getFullYear() + (now.getMonth()+1).toString().padStart(2,'0') + now.getDate().toString().padStart(2,'0') + Math.floor(Math.random()*1000).toString().padStart(3,'0');
        const reporters = ['王先生','李女士','安保部','物业前台','监控中心','张工','刘先生'];
        const categories = ['设施报修','消防告警','设备故障','能耗异常','安防告警'];
        const locations = ['A栋-1F-大堂','B2-Parking-Zone-C','C栋-Elevator-02','B区-配电房','D栋-门禁口','C区-停车场','A栋-Elevator-01'];
        const contents = [
          'A栋大堂天花板漏水，情况紧急，需要立即处理！',
          '地下车库B2区烟雾传感器触发，已派人前往核实。',
          'C栋电梯内有异响，已处理完毕。',
          'B区配电房温度过高，请及时检查。',
          'D栋门禁系统异常刷卡，疑似非法进入。',
          'C区停车场照明损坏，影响夜间安全。',
          'A栋电梯困人报警，已联系救援。'
        ];
        // 只用两种状态
        const status = Math.random() > 0.5 ? 'undispatched' : 'unaccepted';
        const event = {
          id,
          incidentId,
          reporter: reporters[Math.floor(Math.random()*reporters.length)],
          status,
          content: contents[Math.floor(Math.random()*contents.length)],
          location: locations[Math.floor(Math.random()*locations.length)],
          timestamp: now.toLocaleString(),
          category: categories[Math.floor(Math.random()*categories.length)],
          channel: 'App上报',
          source: '业主App'
        };
        incidentData.unshift(event);
        if (incidentData.length > 12) incidentData.pop();
        if (!filterActive) renderIncidentList();
      }, 7000);
    }
    // 启动
    window.onload = function() {
      // 初始化数据状态
      incidentData.forEach(ev => {
        if (ev.status !== 'undispatched' && ev.status !== 'unaccepted') ev.status = 'undispatched';
      });
      renderIncidentList();
      simulateNewIncident();
      startScroll();
    };
  </script>
</body>
</html> 